using System;
using System.Collections.ObjectModel;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using Microsoft.Xna.Framework.Content;

using GameEngine.Content;

namespace GameEngine.Scene
{
    /// <summary>
    /// A scene which contains a collection of GEObjects and is automatically updated, drawn, etc...
    /// </summary>
    public class GEScene
    {
        private GEBaseNode Root;

        public GEBaseNode SceneRoot { get { return Root; } set { Root = value; } }

        public GEScene()
        {
            Root = new GEBaseNode();
        }

        public void AddObject(GEObject newObject)
        {
            GEObjectNode node = new GEObjectNode(newObject);

            Root.AddChild(node);
        }

        public void Update(GameTime gameTime)
        {
            Root.Update(gameTime);
        }

        public void Draw(GraphicsDevice device)
        {
            Root.Draw(device);
        }

        public void LoadContent(GraphicsDevice device, ContentManager content)
        {
            Root.LoadContent(device, content);
        }
    }
    
    /// <summary>
    /// A collection of GEBaseNodes
    /// </summary>
    public class GEBaseNodeCollection : Collection<GEBaseNode> { }


    /// <summary>
    /// The class that all other nodes derive from.
    /// Strange because it contains a collection of itself, that means that it can have children
    /// </summary>
    public class GEBaseNode
    {
        private GEBaseNodeCollection children;

        internal GEBaseNode()
        {
            children = new GEBaseNodeCollection();
        }

        internal void AddChild(GEBaseNode node)
        {
            children.Add(node);
        }

        internal virtual void Update(GameTime gameTime)
        {
            foreach (GEBaseNode node in children)
                node.Update(gameTime);
        }

        internal virtual void Draw(GraphicsDevice device)
        {
            foreach (GEBaseNode node in children)
                node.Draw(device);
        }

        internal virtual void LoadContent(GraphicsDevice device, ContentManager content)
        {
            foreach (GEBaseNode node in children)
                    node.LoadContent(device, content);
        }
    }

    /// <summary>
    /// A node for a scene - needs to be implemented
    /// </summary>
    public class GESceneNode
    {

    }

    /// <summary>
    /// An object node that can be used in a scene
    /// </summary>
    public class GEObjectNode : GEBaseNode
    {
        GEObject NodeObject;

        public GEObjectNode(GEObject newObject)
        {
            NodeObject = newObject;
        }

        internal override void Draw(GraphicsDevice device)
        {
            NodeObject.Draw(device);
        }

        internal override void LoadContent(GraphicsDevice device, ContentManager content)
        {
            if(NodeObject is IGEHasContent)
                ((IGEHasContent)NodeObject).LoadContent(content);
        }
    }
}
